package com.maktoub.project.service.impl;

import cn.hutool.http.HttpResponse;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.maktoub.apiclientstart.client.ApiInterfaceClient;
import com.maktoub.common.model.entity.InterfaceInfo;
import com.maktoub.common.model.entity.User;
import com.maktoub.common.model.entity.UserInterfaceInfo;
import com.maktoub.project.common.BaseResponse;
import com.maktoub.project.common.ErrorCode;
import com.maktoub.project.common.ResultUtils;
import com.maktoub.project.exception.BusinessException;
import com.maktoub.project.mapper.UserInterfaceInfoMapper;
import com.maktoub.project.model.dto.UserInterfaceInfo.UserInterfaceInfoQueryRequest;
import com.maktoub.project.model.vo.UserInterfaceInfoExcludedVO;
import com.maktoub.project.model.vo.UserInterfaceInfoVO;
import com.maktoub.project.service.UserInterfaceInfoService;
import com.maktoub.project.service.UserService;
import com.maktoub.project.utils.ReflexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

/**
* @author Maktoub
* @description 针对表【user_interface_info(用户接口调用)】的数据库操作Service实现
* @createDate 2024-05-16 19:11:10
*/
@Service
@Slf4j
public class UserInterfaceInfoServiceImpl extends ServiceImpl<UserInterfaceInfoMapper, UserInterfaceInfo>
    implements UserInterfaceInfoService{

    @Autowired
    UserInterfaceInfoMapper userInterfaceInfoMapper;

    @Autowired
    UserService userService;
    @Override
    public void validUserInterfaceInfo(UserInterfaceInfo userInterfaceInfo, boolean add) {
        if (userInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = userInterfaceInfo.getId();
        Long userId = userInterfaceInfo.getUserId();
        Long interfaceId = userInterfaceInfo.getInterfaceId();
        Long leftNum = userInterfaceInfo.getLeftNum();
        Long totalNum = userInterfaceInfo.getTotalNum();

        if (add) {
            if (userId<=0||interfaceId<=0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数不能为空");
            }
        }
        else {
            if (id<0){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"修改的id为空！");
            }
        }
        if(leftNum<0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"剩余次数不能小于0");
        }
        if(totalNum<0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"总次数不能小于0");
        }
        if(totalNum<leftNum){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"总次数不能小于剩余次数");
        }


    }

    @Override
    public BaseResponse<Object> requestGatewayWithSDK(User loginUser, ApiInterfaceClient apiInterfaceClient,
                                      InterfaceInfo interfaceInfo, Map<String, Object> requestParams) {

        String accessKey = loginUser.getAccessKey();
        String secrectKey = loginUser.getSecrectKey();
        apiInterfaceClient.setAccessKey(accessKey);
        apiInterfaceClient.setSecrectKey(secrectKey);

        //todook 后期根据接口url或者id进行测试,通过 接口方法名称调用对应方法
        //这里只对里面的固定的url进行测试，只传入调用参数
        String interfaceName = interfaceInfo.getName();//同时也是方法名
        // 抽取从传过来的参数除了id之外的参数
        HashMap<String, Object> paramMap = new HashMap<>();
        HashSet<String> paramNames = new HashSet<>();
        for(Map.Entry<String,Object> entry:requestParams.entrySet()){
            String key = entry.getKey().strip();
            if(!key.equals("id")&&!key.equals("token")){
                paramMap.put(entry.getKey(),entry.getValue());
                paramNames.add(entry.getKey());
            }
        }
        String json = new Gson().toJson(paramMap);
        String res;
        try {
            Class<? extends ApiInterfaceClient> apiInterfaceClientClass = apiInterfaceClient.getClass();
            Method[] declaredMethods = apiInterfaceClientClass.getDeclaredMethods();

            Method resMethod=null;
            Object args=null;
            //api sdk方法遍历
            for(Method item:declaredMethods){
                if((item.getName()).equals(interfaceName)){
                    Class<?>[] parameterTypes = item.getParameterTypes();
                    Set<String> classFieldNames = ReflexUtils.getClassFieldNames(parameterTypes[0]);
                    if(classFieldNames.containsAll(paramNames)){
                        resMethod=item;
                        try {
                            args = new Gson().fromJson(json, parameterTypes[0]);
                        }
                        catch (Exception e){
                            return ResultUtils.error(ErrorCode.PARAMS_ERROR);
                        }
                        break;
                    }
                }
            }
            HttpResponse response=null;
            if(resMethod!=null){
                try {
                    response = (HttpResponse) (resMethod.invoke(apiInterfaceClient, args));
                }
                catch (Exception e){
                    return ResultUtils.error(HttpStatus.BAD_GATEWAY.value(), "服务器异常！");
                }
            }
            else{
                return ResultUtils.error(HttpStatus.NOT_FOUND.value(),"不存在对应的sdk！");
            }

            if (response==null){
                return ResultUtils.error(HttpStatus.NOT_FOUND.value(),"调用失败");
            }
            if (response.getStatus()!= 200){
                return ResultUtils.error(response.getStatus(),response.body());
            }
            res=response.body();
        }
        catch (Exception e){
            log.error("错误信息 {}",e.getMessage());
            throw new BusinessException(ErrorCode.INTERFACE_ERROR);
        }

        try {
            //能解析成json
            BaseResponse baseResponse = new ObjectMapper().readValue(res, BaseResponse.class);
            System.out.println("baseResponse = " + baseResponse);
            //返回正常
            if (baseResponse.getCode() != 200) {
                throw new BusinessException(ErrorCode.INTERFACE_ERROR);
            }
        }
        catch (JsonProcessingException e){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }

        return ResultUtils.success(res);
    }

    @Override
    public List<UserInterfaceInfoVO> getByUserId(UserInterfaceInfoQueryRequest userInterfaceInfoQueryRequest) {

        List<UserInterfaceInfoVO>  userInterfaceInfoVO = userInterfaceInfoMapper.selectByUserId(userInterfaceInfoQueryRequest);
        return userInterfaceInfoVO;
    }

    @Override
    public Page<UserInterfaceInfoExcludedVO> getByExcluedUserId(UserInterfaceInfoQueryRequest userInterfaceInfoQueryRequest,
                                                                HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if(loginUser==null){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        Long userId = loginUser.getId();
        userInterfaceInfoQueryRequest.setUserId(userId);

        List<UserInterfaceInfoExcludedVO> userInterfaceInfoExcludedVOS =
                userInterfaceInfoMapper.selectByExcluedUserId(userInterfaceInfoQueryRequest);
        Page<UserInterfaceInfoExcludedVO> page = new Page<>(userInterfaceInfoQueryRequest.getCurrent(), userInterfaceInfoExcludedVOS.size());

        long maxNum = userInterfaceInfoMapper.selectByExcluedUserIdCount(userInterfaceInfoQueryRequest);
        int total = userInterfaceInfoExcludedVOS.size(); // 获取总记录数
        page.setRecords(userInterfaceInfoExcludedVOS);
        page.setTotal(maxNum);

        return page;
    }
}




